<?php


namespace apps\marriage\core\service;


use apps\marriage\core\model\CourseOrder;
use apps\marriage\core\model\MatchmakerSpreadSalaryRecord;
use apps\marriage\core\model\PlatformAccountBook;
use apps\marriage\core\model\UserAccountBook;
use apps\marriage\core\payment\IPayOrder;
use think\Exception;
use vm\com\BaseService;

class CourseOrderService extends BaseService implements IPayOrder
{

    /**
     * @return CourseOrder
     */
    protected function getModel()
    {
        return new CourseOrder();
    }

    /**
     * @return UserService
     */
    protected function getUserService()
    {
        return service('User', SERVICE_NAMESPACE);
    }

    /**
     * @return UserAccountBookService
     */
    protected function getUserAccountBookService()
    {
        return service('UserAccountBook', SERVICE_NAMESPACE);
    }

    /**
     * @return CourseService
     */
    protected function getCourseService()
    {
        return service('Course', SERVICE_NAMESPACE);
    }

    /**
     * @return PlatformAccountBookService
     */
    protected function getPlatformAccountBookService()
    {
        return service('PlatformAccountBook', SERVICE_NAMESPACE);
    }

    /**
     * @return BaseService|MatchmakerSpreadSalaryRecordService
     */
    private function getMatchmakerSpreadSalaryRecordService()
    {
        return service('MatchmakerSpreadSalaryRecord', SERVICE_NAMESPACE);
    }

    private function genSn()
    {
        while (true) {
            $sn = date('ymdHis') . rand_string(6, 1);
            if (!parent::info(['sn' => $sn])) {
                return $sn;
            }
        }
    }

    public function getBySn($sn)
    {
        return $this->info(['sn' => $sn]);
    }

    public function createOrder(array $data, $moneyType = 'money')
    {
        $lastOrder = $this->info([
            'user_id' => $data['user_id'],
            'course_id' => $data['course_id'],
            'pay_status' => CourseOrder::PAY_STATUS_PAIED
        ]);
        if($lastOrder) {
            throw new Exception('您已购买该课程');
        }
        $data['sn'] = $this->genSn();
        $data['order_status'] = CourseOrder::ORDER_STATUS_CONFIRMED;
        $data['pay_status'] = CourseOrder::PAY_STATUS_UNPAIED;
        $data['dateline'] = time();
        $orderId = parent::create($data);
        if($data['pay_money'] == 0) {
            $this->payConfirm($orderId, time(), '免费', '', false);
        } elseif ($data['pay_money'] > 0 && $moneyType == 'gold_coin') {
            $this->getUserService()->decreaseGoldCoin($data['user_id'], $data['pay_money'], false);
            $this->payConfirm($orderId, time(), '金币', '', false);
            // 记录消费
            $this->getUserAccountBookService()->record($data['user_id'], UserAccountBook::OP_DECREASE, $data['pay_money'], UserAccountBook::MONEY_TYPE_GOLD_COIN, UserAccountBook::IID_TYPE_COURSE, $orderId, '', '购买课程');
            // 记录平台收支
            $this->getPlatformAccountBookService()->record(PlatformAccountBook::TYPE_INCOME, $data['pay_money'], PlatformAccountBook::IID_TYPE_COURSE, $orderId, null, '购买课程');
            // 计算佣金
            $this->getMatchmakerSpreadSalaryRecordService()->onComputeSalary(MatchmakerSpreadSalaryRecord::IID_TYPE_COURSE, $orderId);
        }
        return $data['sn'];
    }

    public function onPayByGoldCoin($orderSn)
    {
        $order = $this->info(['sn' => $orderSn]);
        if(empty($order)
            || $order['order_status'] != CourseOrder::ORDER_STATUS_CONFIRMED
            || $order['pay_status'] != CourseOrder::PAY_STATUS_UNPAIED) {
            throw new Exception('订单不存在');
        }
        $this->getUserService()->decreaseGoldCoin($order['user_id'], $order['pay_money'], true, '购买课程', UserAccountBook::IID_TYPE_COURSE, $order['id']);
        $this->payConfirm($order['id'], time(), '金币', '');
    }

    /**
     * 修改金额
     * @param $orderId              订单ID
     * @param $money               订单金额
     * @param $payMoney            实付金额
     * @return bool|BaseService
     * @throws Exception
     */
    public function modifyMoney($orderId, $money, $payMoney)
    {
        $order = $this->getByPk($orderId);
        if ($order['order_status'] != CourseOrder::ORDER_STATUS_CONFIRMED || $order['pay_status'] != CourseOrder::PAY_STATUS_UNPAIED) {
            throw new Exception('只有已确认待付款订单才可修改金额');
        }
        $data = [
            'id' => $orderId,
            'money' => $money,
            'pay_money' => $payMoney,
            'discount_money' => $money - $payMoney
        ];
        if ($this->updateByPk($data)) {
            // TODO: 给用户发送通知

            return true;
        }
        throw new Exception('操作失败');
    }

    /**
     * 修改订单状态
     * @param $orderId              订单ID
     * @param $orderStatus          订单状态
     * @return bool|BaseService
     * @throws Exception
     */
    public function modifyStatus($orderId, $orderStatus)
    {
        $order = $this->getByPk($orderId);
        if (!in_array($order['order_status'], [
                CourseOrder::ORDER_STATUS_CONFIRMED,
                CourseOrder::ORDER_STATUS_STUDYING,
                CourseOrder::ORDER_STATUS_FINISHED
            ]) || !in_array($orderStatus, [
                CourseOrder::ORDER_STATUS_CONFIRMED,
                CourseOrder::ORDER_STATUS_STUDYING,
                CourseOrder::ORDER_STATUS_FINISHED
            ])) {
            throw new Exception('状态错误');
        }
        $data = [
            'id' => $orderId,
            'order_status' => $orderStatus
        ];
        return $this->updateByPk($data);
    }

    public function onCancel($orderSn)
    {
        $order = $this->getBySn($orderSn);
        if($order['order_status'] != CourseOrder::ORDER_STATUS_CONFIRMED
            || $order['pay_status'] != CourseOrder::PAY_STATUS_UNPAIED) {
            throw new Exception('订单不能取消');
        }
        return $this->updateByPk([
           'id' => $order['id'],
           'order_status' => CourseOrder::ORDER_STATUS_CANCELLED
        ]);
    }

    public function onModifyOrderMoney($orderSn, $orderMoney)
    {
        $order = $this->getBySn($orderSn);
        if($order['order_status'] != CourseOrder::ORDER_STATUS_CONFIRMED
            || $order['pay_status'] != CourseOrder::PAY_STATUS_UNPAIED) {
            throw new Exception('订单不能修改金额');
        }
        return $this->updateByPk([
            'id' => $order['id'],
            'pay_money' => $orderMoney
        ]);
    }

    /**
     * 创建支付交易后回调
     * @param $orderId
     * @param $tradeNo
     * @return mixed
     */
    public function onPayTradeCreated($orderId, $tradeNo)
    {
        return $this->updateByPk([
            'id' => $orderId,
            'pay_trade_no' => $tradeNo
        ]);
    }

    /**
     * 支付成功后回调
     * @param $tradeNo              本站支付流水号
     * @param $transactionId        第三方支付平台流水号
     * @param $payTime              付款时间
     * @param $paymentName          支付方式名称
     * @return mixed
     */
    public function onPaySuccess($tradeNo, $transactionId, $payTime, $paymentName)
    {
        $order = $this->info([
            'pay_trade_no' => $tradeNo
        ]);
        if (!$order) {
            throw new Exception('订单不存在');
        }
        return $this->payConfirm($order['id'], $payTime, $paymentName, $transactionId);
    }

    /**
     * 后台确认已付款
     * @param $orderId              订单ID
     * @param $payTime              付款时间
     * @param $payPlatformName      支付平台名称
     * @param $payPlatformTradeNo   支付平台流水号
     * @return bool
     * @throws
     */
    public function payConfirm($orderId, $payTime, $payPlatformName, $payPlatformTradeNo, $record = true)
    {
        $order = $this->getByPk($orderId);
        if ($order['order_status'] != CourseOrder::ORDER_STATUS_CONFIRMED || $order['pay_status'] != CourseOrder::PAY_STATUS_UNPAIED) {
            throw new Exception('只有已确认待付款订单才可确认付款');
        }
        $data = [
            'id' => $orderId,
            'order_status' => CourseOrder::ORDER_STATUS_FINISHED,
            'pay_status' => CourseOrder::PAY_STATUS_PAIED,
            'pay_time' => $payTime,
            'pay_platform_trade_no' => $payPlatformTradeNo,
            'pay_platform_name' => $payPlatformName
        ];
//        // 在线课程：将订单状态改为上课中
//        $course = $this->getCourseService()->getByPk($order['course_id']);
//        if ($course['is_online'] == 1) {
//            $data['order_status'] = CourseOrder::ORDER_STATUS_STUDYING;
//        }
        if ($this->updateByPk($data)) {
            $this->getCourseService()->increase('apply_amount', ['id' => $order['course_id']]);
            if($record) {
                // 记录消费
                $this->getUserAccountBookService()->record($order['user_id'], UserAccountBook::OP_DECREASE, $order['pay_money'], UserAccountBook::MONEY_TYPE_MONEY, UserAccountBook::IID_TYPE_COURSE, $orderId, '', '购买课程');
                // 记录平台收支
                $this->getPlatformAccountBookService()->record(PlatformAccountBook::TYPE_INCOME, $order['pay_money'], PlatformAccountBook::IID_TYPE_COURSE, $orderId, null, '购买课程');
            }
            // TODO: 给用户发送通知


            // 计算佣金
            $this->getMatchmakerSpreadSalaryRecordService()->onComputeSalary(MatchmakerSpreadSalaryRecord::IID_TYPE_COURSE, $orderId);
            return true;
        }

        throw new Exception('操作失败');
    }

    /**
     * 申请退款
     * @param $orderId  订单ID
     * @return bool
     * @throws
     */
    public function refundApply($orderId)
    {
        $order = $this->getByPk($orderId);
        if (!in_array($order['pay_status'], [
                CourseOrder::PAY_STATUS_PAIED
            ]) || !in_array($order['order_status'], [
                CourseOrder::ORDER_STATUS_CONFIRMED,
//                CompanyCourseOrder::ORDER_STATUS_STUDYING
            ])) {
            throw new Exception('状态错误');
        }
        $data = [
            'id' => $orderId,
            'order_status' => CourseOrder::ORDER_STATUS_REFUND_AUDITING,
            'refund_apply_time' => time()
        ];
        if ($this->updateByPk($data)) {
            // TODO: 给用户发送通知

            return true;
        }
        throw new Exception('操作失败');
    }

    /**
     * 退款审核
     * @param $orderId              订单ID
     * @param $orderStatus          订单状态
     * @return bool|BaseService
     * @throws Exception
     */
    public function refundAudit($orderId, $orderStatus)
    {
        $order = $this->getByPk($orderId);
        if (!in_array($order['order_status'], [
                CourseOrder::ORDER_STATUS_REFUND_AUDITING
            ]) || !in_array($orderStatus, [
                CourseOrder::ORDER_STATUS_CONFIRMED,
                CourseOrder::ORDER_STATUS_REFUNDING
            ])) {
            throw new Exception('状态错误');
        }
        $data = [
            'id' => $orderId,
            'order_status' => $orderStatus
        ];
        if ($orderStatus == CourseOrder::ORDER_STATUS_REFUNDING) {
            $data['refund_confirm_time'] = time();
        }
        if ($this->updateByPk($data)) {
            // TODO: 给用户发送通知

            return true;
        }
        throw new Exception('操作失败');
    }

    /**
     * 退款打款
     * @param $orderId              订单ID
     * @param $refundPayTime        打款时间
     * @return bool|BaseService
     * @throws Exception
     */
    public function refundPay($orderId, $refundPayTime)
    {
        $order = $this->getByPk($orderId);
        if (!in_array($order['order_status'], [
            CourseOrder::ORDER_STATUS_REFUNDING
        ])) {
            throw new Exception('状态错误');
        }
        $data = [
            'id' => $orderId,
            'order_status' => CourseOrder::ORDER_STATUS_REFUNDED,
            'refund_pay_time' => $refundPayTime
        ];
        if ($this->updateByPk($data)) {
            // TODO: 给用户发送通知

            return true;
        }
        throw new Exception('操作失败');
    }

    public function format(array $data)
    {
        $data['pay_status_label'] = CourseOrder::getCoursePayStatusLabel($data['pay_status']);
        $data['order_status_label'] = CourseOrder::getCourseOrderStatusLabel($data['order_status']);

        return $data;
    }
}